<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Proxy代理-特性</title>
</head>

<body>
  <script>
    /* 
      Proxy特性
    */

    // 1.陷阱
    // 示例：
    // 当读取对象上不存在属性时，不会报错而是返回undefined，用get()方法就能改变默认方法
    var obj1 = {
      name: "strick"
    }

    var handler1 = {
      get(target, propety, receiver) {
        if(propety in target) {
          return target[propety]
        }

        throw "未定义的错误"
      }
    }

    var p1 = new Proxy(obj1, handler1)
    p1.name
    p1.age

    // 在众多陷阱中只有apply()和construct()的目标对象是函数
    function getName(name) {
      return name
    }

    var obj2 = {
      prefix: "hello"
    }

    var handler2 = {
      apply(target, thisArg, argumentsList) {
        if(thisArg && thisArg.prefix) {
          return target(thisArg.prefix + argumentsList[0])
        }

        return target(...argumentsList)
      }
    }

    var p2 = new Proxy(getName, handler2)
    p2("strick")
    p2.call(obj2, "strick")

    // 2.撤销代理
    // Proxy.revocable 返回一个对象，有两个属性proxy和revoke
    var obj3 = {}
    var handler3 = {}
    let {proxy, revoke} = Proxy.revocable(obj3, handler3)
    revoke()
    delete proxy.name
    typeof proxy

    // 3.原型
    var obj4 = {
      name: "strick"
    }

    var handler4 = {
      get(target, propety, receiver) {
        if(propety === "name") {
          return "hello " + target[propety]
        }
        return true
      }
    }

    var p4 = new Proxy({}, handler4)
    Object.setPrototypeOf(obj4, p4)
    obj.name      // 自有属性 不会触发拦截
    obj.age       // 不是自有属性，会从原型链找，故返回true
  </script>
</body>

</html>